﻿using ArtMath.Core.Data;
using System;
using System.Collections.Generic;

namespace ArtMath.Core.Helper
{
    /// <summary>
    /// 求两曲线交点类
    /// </summary>
    public static class CurveIntersection
    {
        //public static PointD[] GetCrossPoints(LineBase line1, LineBase line2, Predicate<List<PointD>> judge = null, bool getNew = true)
        //{
        //    PointD[] pts = line1.GetCrossPoints(line2, getNew);
        //    if (pts == null)
        //    {
        //        pts = line2.GetCrossPoints(line1, getNew);
        //        if (pts == null)
        //        {
        //            ICurveLike curs1 = line1 as ICurveLike, curs2 = line2 as ICurveLike;
        //            if (curs1 != null && curs2 != null)
        //            {
        //                List<PointD> tmp = new List<PointD>();
        //                foreach (Curve cur1 in getNew ? curs1.NewCurves : curs1.Curves)
        //                {
        //                    foreach (Curve cur2 in getNew ? curs2.NewCurves : curs2.Curves)
        //                    {
        //                        pts = cur1.CurvesIntersection(cur2, judge);
        //                        if (pts != null) tmp.AddRange(pts);
        //                    }
        //                }
        //                pts = tmp.ToArray();
        //            }
        //        }
        //    }
        //    if (pts == null) return null;
        //    List<PointD> res = new List<PointD>();
        //    foreach (PointD item in pts)
        //    {
        //        if (item.IsNumberPoint)
        //        {
        //            res.Add(item);
        //        }
        //    }
        //    return res.Count == 0 ? null : res.ToArray();
        //}
        public static PointD[] CurvesIntersection(IList<PointD> cur1, bool close1, IList<PointD> cur2, bool close2, Predicate<List<PointD>> judge = null)
        {
            List<PointD> res = new List<PointD>();
            for (int i = 0; i < cur1.Count; i++)
            {
                int iNext;
                if (i == cur1.Count - 1)
                {
                    if (close1)
                    {
                        iNext = 0;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    iNext = i + 1;
                }
                PointD[] tmp = LineSegmentCurveIntersection(cur1[i], cur1[iNext], cur2, close2);//无效点在这里排除
                if (tmp != null)
                {
                    res.AddRange(tmp);
                    if (judge != null && judge(res)) break;
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] LineSegmentCurveIntersection(PointD segpt1, PointD segpt2, IList<PointD> cur, bool close, Predicate<List<PointD>> judge = null)
        {
            List<PointD> res = new List<PointD>();
            for (int i = 0; i < cur.Count; i++)
            {
                int iNext;
                if (i == cur.Count - 1)
                {
                    if (close)
                    {
                        iNext = 0;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    iNext = i + 1;
                }
                PointD[] tmp = LineSegmentsIntersection(segpt1, segpt2, cur[i], cur[iNext]);
                if (tmp != null)
                {
                    res.AddRange(tmp);
                    if (judge != null && judge(res)) break;
                }
            }
            removeInvalidPoints(res);
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] RayCurveIntersection(PointD pt, double angle, IList<PointD> cur, bool close, Predicate<List<PointD>> judge = null)
        {
            List<PointD> res = new List<PointD>();
            for (int i = 0; i < cur.Count; i++)
            {
                int iNext;
                if (i == cur.Count - 1)
                {
                    if (close)
                    {
                        iNext = 0;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    iNext = i + 1;
                }
                PointD[] tmp = LineSegmentRayIntersection(cur[i], cur[iNext], pt, angle);
                if (tmp != null)
                {
                    res.AddRange(tmp);
                    if (judge != null && judge(res)) break;
                }
            }
            removeInvalidPoints(res);
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] StraightLineCurveIntersection(PointD linept, double lineSlope, IList<PointD> cur, bool close, Predicate<List<PointD>> judge = null)
        {
            List<PointD> res = new List<PointD>();
            for (int i = 0; i < cur.Count; i++)
            {
                int iNext;
                if (i == cur.Count - 1)
                {
                    if (close)
                    {
                        iNext = 0;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    iNext = i + 1;
                }
                PointD[] tmp = LineSegmentStraightLineIntersection(cur[i], cur[iNext], linept, lineSlope);
                if (tmp != null)
                {
                    res.AddRange(tmp);
                    if (judge != null && judge(res)) break;
                }
            }
            removeInvalidPoints(res);
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] StraightLineCurveIntersection(double A, double B, double C, IList<PointD> cur, bool close, Predicate<List<PointD>> judge = null)
        {
            List<PointD> res = new List<PointD>();
            for (int i = 0; i < cur.Count; i++)
            {
                int iNext;
                if (i == cur.Count - 1)
                {
                    if (close)
                    {
                        iNext = 0;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    iNext = i + 1;
                }
                PointD[] tmp = LineSegmentStraightLineIntersection(cur[i], cur[iNext], A, B, C);
                if (tmp != null)
                {
                    res.AddRange(tmp);
                    if (judge != null && judge(res)) break;
                }
            }
            removeInvalidPoints(res);
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] ArcCircleIntersection(PointD ct1, double r1, double start1, double sweep1, PointD ct2, double r2)
        {
            return ArcsIntersection(ct1, r1, start1, sweep1, ct2, r2, 0, Angle.RadRound);
        }
        public static PointD[] CirclesIntersection(PointD ct1, double r1, PointD ct2, double r2)
        {
            return ArcsIntersection(ct1, r1, 0, Angle.RadRound, ct2, r2, 0, Angle.RadRound);
        }
        //public static PointD[] CircleObjectIntersection(SketchPad pad, PointD center, double radius, ShapeBase obj, bool getNew = true)
        //{
        //    List<PointD> res = new List<PointD>();
        //    PointD[] pts = null;
        //    LineSegmentBase lsb = obj as LineSegmentBase;
        //    if (lsb != null)
        //    {
        //        pts = getNew ? LineSegmentCircleIntersection(lsb.Point1.NewXY, lsb.Point2.NewXY, center, radius) :
        //            LineSegmentCircleIntersection(lsb.Point1.ToPointD(), lsb.Point2.ToPointD(), center, radius);
        //    }
        //    else
        //    {
        //        RayBase ray = obj as RayBase;
        //        if (ray != null)
        //        {
        //            pts = getNew ? RayCircleIntersection(ray.SourcePoint.NewXY, ray.NewDirectedAngle, center, radius) :
        //                RayCircleIntersection(ray.SourcePoint.ToPointD(), ray.DirectedAngle.RadValue, center, radius);
        //        }
        //        else
        //        {
        //            PointSlopeLineBase slb = obj as PointSlopeLineBase;
        //            if (slb != null)
        //            {
        //                pts = getNew ? StraightLineCircleIntersection(slb.NewA, slb.NewB, slb.NewC, center, radius) :
        //                    StraightLineCircleIntersection(slb.A, slb.B, slb.C, center, radius);
        //            }
        //            else
        //            {
        //                ThreePointsPartialCircleBase tppcb = obj as ThreePointsPartialCircleBase;
        //                if (tppcb != null)
        //                {
        //                    pts = getNew ? ArcCircleIntersection(tppcb.NewCenter, tppcb.NewRadius, tppcb.NewStart, tppcb.NewSweep, center, radius) :
        //                        ArcCircleIntersection(tppcb.Center, tppcb.Radius, tppcb.Start.RadValue, tppcb.Sweep.RadValue, center,radius);
        //                }
        //                else
        //                {
        //                    CircleLikeBase clb = obj as CircleLikeBase;
        //                    if (clb != null)
        //                    {
        //                        pts = getNew ? CirclesIntersection(center, radius, clb.NewCenter, clb.NewRadius) :
        //                             CirclesIntersection(center, radius, clb.Center, clb.Radius);
        //                    }
        //                    else
        //                    {
        //                        ICurveLike curs = obj as ICurveLike;
        //                        if (curs != null)
        //                        {
        //                            PaintableCurve cur = new PaintableCurve();
        //                            pad.BuildCircleSamples(cur, center, radius);
        //                            foreach (PaintableCurve item in getNew ? curs.NewCurves : curs.Curves)
        //                            {
        //                                pts = cur.CurvesIntersection(item);
        //                                if (pts != null) res.AddRange(pts);
        //                            }
        //                            pts = null;
        //                        }
        //                        else
        //                        {
        //                            if (obj is PolygonBase || obj is AngleNDivider || obj is CoordinateBase)//直线+直线组
        //                            {
        //                                foreach (StraightLineBase item in obj.GetStraightLines())
        //                                {
        //                                    pts = CircleObjectIntersection(pad, center, radius, item, getNew);
        //                                    if (pts != null) res.AddRange(pts);
        //                                }
        //                                pts = null;
        //                            }
        //                        }
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    if (pts != null)
        //    {
        //        if (pad.Coordinate != null)
        //        {
        //            for (int i = 0; i < pts.Length; i++)
        //            {
        //                pts[i] = pad.Coordinate.XYToPxy(pts[i]);
        //            }
        //        }
        //        res.AddRange(pts);
        //    }
        //    if (res.Count == 0) return null;
        //    return res.ToArray();
        //}
        public static PointD[] ArcsIntersection(PointD ct1, double r1, double start1, double sweep1, PointD ct2, double r2, double start2, double sweep2)
        {
            double delta = ct1.DistanceTo(ct2) - r1 - r2;
            if (delta > 0) return null;
            List<PointD> pts = new List<PointD>();
            if (delta == 0)
            {
                pts.Add(Utility.RatePoint(ct1, ct2, r1 / r2));
            }
            else
            {
                delta = ct1.DistanceTo(ct2) - Math.Abs(r1 - r2);
                if (delta < 0) return null;
                if (delta == 0)
                {
                    pts.Add((ct2 * r1 / r2 - ct1) * r2 / (r1 - r2));
                }
                else
                {
                    if (ct1.X == ct2.X)
                    {
                        double xp1 = ct1.X * (ct2.Y - ct1.Y),
                            xp2 = 0.5 * Math.Sqrt(-6 * ct1.Y * ct1.Y * ct2.Y * ct2.Y + 2 * ct1.Y * ct1.Y * r2 * r2 - 4 * ct1.Y * ct2.Y * r1 * r1 + 2 * ct2.Y * ct2.Y * r2 * r2 - 4 * ct1.Y * ct2.Y * r2 * r2 + 4 * ct1.Y * ct1.Y * ct1.Y * ct2.Y + 4 * ct1.Y * ct2.Y * ct2.Y * ct2.Y - r1 * r1 * r1 * r1 - r2 * r2 * r2 * r2 + 2 * r2 * r2 * r1 * r1 + 2 * ct1.Y * ct1.Y * r1 * r1 - ct2.Y * ct2.Y * ct2.Y * ct2.Y + 2 * ct2.Y * ct2.Y * r1 * r1 - ct1.Y * ct1.Y * ct1.Y * ct1.Y),
                            xp3 = ct2.Y - ct1.Y,
                            y = -0.5 * (r2 * r2 - ct2.Y * ct2.Y + ct1.Y * ct1.Y - r1 * r1) / xp3;
                        pts.Add(new PointD((xp1 + xp2) / xp3, y));
                        pts.Add(new PointD((xp1 - xp2) / xp3, y));
                    }
                    else
                    {
                        double yp1 = 0.5 / (-8 * ct2.Y * ct1.Y - 8 * ct1.X * ct2.X + 4 * ct1.Y * ct1.Y + 4 * ct2.X * ct2.X + 4 * ct1.X * ct1.X + 4 * ct2.Y * ct2.Y),
                            yp2 = 4 * ct2.Y * ct2.Y * ct2.Y - 8 * ct1.X * ct2.X * ct2.Y - 8 * ct1.X * ct2.X * ct1.Y - 4 * ct2.Y * ct1.Y * ct1.Y - 4 * r1 * r1 * ct1.Y + 4 * ct2.Y * ct1.X * ct1.X + 4 * ct2.X * ct2.X * ct1.Y + 4 * ct2.X * ct2.X * ct2.Y - 4 * r2 * r2 * ct2.Y - 4 * ct2.Y * ct2.Y * ct1.Y + 4 * ct1.Y * ct1.Y * ct1.Y + 4 * ct1.X * ct1.X * ct1.Y + 4 * r2 * r2 * ct1.Y + 4 * ct2.Y * r1 * r1,
                            yp3 = 4 * Math.Sqrt(-r1 * r1 * r1 * r1 * ct2.X * ct2.X - 16 * ct1.X * ct2.X * ct2.X * ct2.X * ct2.Y * ct1.Y - 4 * ct1.X * ct2.X * ct2.Y * ct2.Y * r2 * r2 + 12 * ct1.X * ct2.X * ct2.Y * ct2.Y * ct1.Y * ct1.Y - r1 * r1 * r1 * r1 * ct1.X * ct1.X + 24 * ct1.X * ct1.X * ct2.X * ct2.X * ct2.Y * ct1.Y - ct2.Y * ct2.Y * ct2.Y * ct2.Y * ct2.X * ct2.X - ct2.Y * ct2.Y * ct2.Y * ct2.Y * ct1.X * ct1.X + 4 * ct2.Y * ct2.Y * ct2.Y * ct2.X * ct2.X * ct1.Y + 2 * r1 * r1 * r1 * r1 * ct1.X * ct2.X - 8 * ct1.X * ct2.X * ct2.Y * ct1.Y * ct1.Y * ct1.Y - 16 * ct1.X * ct1.X * ct1.X * ct2.X * ct2.Y * ct1.Y - 4 * ct1.X * ct2.X * ct2.Y * ct2.Y * r1 * r1 - 4 * ct1.X * ct2.X * ct1.Y * ct1.Y * r1 * r1 - 4 * ct1.X * ct2.X * ct1.Y * ct1.Y * r2 * r2 - 4 * r1 * r1 * ct1.Y * ct2.Y * ct1.X * ct1.X - 4 * r1 * r1 * ct1.Y * ct2.X * ct2.X * ct2.Y - 4 * ct2.Y * ct1.X * ct1.X * r2 * r2 * ct1.Y - 4 * ct2.X * ct2.X * ct1.Y * r2 * r2 * ct2.Y - 4 * ct1.X * ct2.X * r2 * r2 * r1 * r1 + 2 * ct2.Y * ct2.Y * ct2.Y * ct2.Y * ct1.X * ct2.X + 4 * ct2.Y * ct2.Y * ct2.Y * ct1.X * ct1.X * ct1.Y - 12 * ct1.X * ct1.X * ct2.X * ct2.X * ct2.Y * ct2.Y + 8 * ct1.X * ct1.X * ct1.X * ct2.X * ct2.Y * ct2.Y + 8 * ct1.X * ct2.X * ct2.X * ct2.X * ct2.Y * ct2.Y + 8 * ct1.X * ct2.X * ct2.X * ct2.X * ct1.Y * ct1.Y + 8 * ct1.X * ct1.X * ct1.X * ct2.X * ct1.Y * ct1.Y - 6 * ct2.Y * ct2.Y * ct1.Y * ct1.Y * ct1.X * ct1.X + 4 * ct2.Y * ct1.Y * ct1.Y * ct1.Y * ct2.X * ct2.X - 6 * ct2.Y * ct2.Y * ct1.Y * ct1.Y * ct2.X * ct2.X + 4 * ct2.Y * ct1.Y * ct1.Y * ct1.Y * ct1.X * ct1.X - ct2.X * ct2.X * ct2.X * ct2.X * ct2.X * ct2.X - ct1.X * ct1.X * ct1.X * ct1.X * ct1.X * ct1.X + 8 * ct1.X * ct2.X * ct2.Y * r1 * r1 * ct1.Y + 2 * ct1.X * ct2.X * ct1.Y * ct1.Y * ct1.Y * ct1.Y + 8 * ct1.X * ct2.X * ct2.Y * r2 * r2 * ct1.Y - 12 * ct1.X * ct1.X * ct2.X * ct2.X * ct1.Y * ct1.Y - 8 * ct2.Y * ct2.Y * ct2.Y * ct1.X * ct2.X * ct1.Y + 2 * r1 * r1 * ct1.Y * ct1.Y * ct2.X * ct2.X + 2 * r1 * r1 * ct1.Y * ct1.Y * ct1.X * ct1.X + 2 * ct2.Y * ct2.Y * ct1.X * ct1.X * r2 * r2 + 4 * ct2.Y * ct1.X * ct1.X * ct1.X * ct1.X * ct1.Y + 2 * ct2.Y * ct2.Y * ct1.X * ct1.X * r1 * r1 + 4 * ct2.X * ct2.X * ct2.X * ct2.X * ct1.Y * ct2.Y + 2 * ct2.X * ct2.X * ct1.Y * ct1.Y * r2 * r2 + 2 * ct2.X * ct2.X * ct2.Y * ct2.Y * r2 * r2 + 2 * ct2.X * ct2.X * ct2.Y * ct2.Y * r1 * r1 + 2 * ct2.X * ct2.X * r2 * r2 * r1 * r1 + 2 * ct1.X * ct1.X * r2 * r2 * r1 * r1 - 2 * ct2.Y * ct2.Y * ct1.X * ct1.X * ct1.X * ct1.X - 2 * ct2.X * ct2.X * ct2.X * ct2.X * ct1.Y * ct1.Y - ct2.X * ct2.X * ct1.Y * ct1.Y * ct1.Y * ct1.Y - 2 * ct2.X * ct2.X * ct2.X * ct2.X * ct2.Y * ct2.Y - ct1.Y * ct1.Y * ct1.Y * ct1.Y * ct1.X * ct1.X - 2 * ct1.X * ct1.X * ct1.X * ct1.X * ct1.Y * ct1.Y + 6 * ct1.X * ct2.X * ct2.X * ct2.X * ct2.X * ct2.X + 6 * ct1.X * ct1.X * ct1.X * ct1.X * ct1.X * ct2.X - 15 * ct1.X * ct1.X * ct2.X * ct2.X * ct2.X * ct2.X - 15 * ct1.X * ct1.X * ct1.X * ct1.X * ct2.X * ct2.X + 20 * ct1.X * ct1.X * ct1.X * ct2.X * ct2.X * ct2.X - ct2.X * ct2.X * r2 * r2 * r2 * r2 + 2 * ct2.X * ct2.X * ct2.X * ct2.X * r1 * r1 + 2 * ct2.X * ct2.X * ct2.X * ct2.X * r2 * r2 - ct1.X * ct1.X * r2 * r2 * r2 * r2 + 2 * ct1.X * ct1.X * ct1.X * ct1.X * r1 * r1 + 2 * ct1.X * ct1.X * ct1.X * ct1.X * r2 * r2 + 2 * ct1.X * ct1.X * ct1.Y * ct1.Y * r2 * r2 + 12 * ct1.X * ct1.X * ct2.X * ct2.X * r2 * r2 + 12 * ct1.X * ct1.X * ct2.X * ct2.X * r1 * r1 + 2 * ct1.X * ct2.X * r2 * r2 * r2 * r2 - 8 * ct1.X * ct2.X * ct2.X * ct2.X * r1 * r1 - 8 * ct1.X * ct2.X * ct2.X * ct2.X * r2 * r2 - 8 * ct1.X * ct1.X * ct1.X * ct2.X * r1 * r1 - 8 * ct1.X * ct1.X * ct1.X * ct2.X * r2 * r2);
                        double xp1 = ct2.X * ct2.X + ct2.Y * ct2.Y - r2 * r2 - ct1.X * ct1.X - ct1.Y * ct1.Y + r1 * r1;
                        pts.Add(new PointD(-0.5 * (-2 * yp1 * (yp2 + yp3) * ct2.Y + 2 * yp1 * (yp2 + yp3) * ct1.Y + xp1) / (ct1.X - ct2.X), yp1 * (yp2 + yp3)));
                        pts.Add(new PointD(-0.5 * (-2 * yp1 * (yp2 - yp3) * ct2.Y + 2 * yp1 * (yp2 - yp3) * ct1.Y + xp1) / (ct1.X - ct2.X), yp1 * (yp2 - yp3)));
                    }
                }
            }
            for (int i = pts.Count - 1; i >= 0; i--)
            {
                if (!pts[i].IsNumberPoint || !Utility.InSweepRange(start1, sweep1, ct1.GetAngle(pts[i])) || !Utility.InSweepRange(start2, sweep2, ct2.GetAngle(pts[i])))
                {
                    pts.RemoveAt(i);
                }
            }
            if (pts.Count == 0) return null;
            return pts.ToArray();
        }
        //public static PointD[] CircleCurveIntersection(PointD ct, double r, Curve cur, Predicate<List<PointD>> judge = null)
        //{
        //    return CircleCurveIntersection(ct, r, cur.Samples, cur.IsClosed, judge);
        //}
        //public static PointD[] CircleCurveIntersection(PointD ct, double r, IList<PointD> cur, bool close, Predicate<List<PointD>> judge = null)
        //{
        //    List<PointD> res = new List<PointD>();
        //    for (int i = 0; i < cur.Count; i++)
        //    {
        //        int iNext;
        //        if (i == cur.Count - 1)
        //        {
        //            if (close)
        //            {
        //                iNext = 0;
        //            }
        //            else
        //            {
        //                continue;
        //            }
        //        }
        //        else
        //        {
        //            iNext = i + 1;
        //        }
        //        PointD[] pts = LineSegmentCircleIntersection(cur[i], cur[iNext], ct, r);
        //        if (pts != null)
        //        {
        //            res.AddRange(pts);
        //            if (judge != null && judge(res)) break;
        //        }
        //    }
        //    if (res.Count == 0) return null;
        //    return res.ToArray();
        //}
        public static PointD[] LineSegmentCircleIntersection(PointD segpt1, PointD segpt2, PointD ct, double r)
        {
            return LineSegmentArcIntersection(segpt1, segpt2, ct, r, 0, Angle.RadRound);
        }
        public static PointD[] LineSegmentArcIntersection(PointD segpt1, PointD segpt2, PointD ct, double r, double start, double sweep)
        {
            double[] ABC = segpt1.GetABC(segpt2);
            PointD[] tmp = StraightLineArcIntersection(ABC[0], ABC[1], ABC[2], ct, r, start, sweep);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(item, segpt1, item, segpt2) <= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] RayCircleIntersection(PointD pt, double angle, PointD ct, double r)
        {
            return RayArcIntersection(pt, angle, ct, r, 0, Angle.RadRound);
        }
        public static PointD[] RayArcIntersection(PointD pt, double angle, PointD ct, double r, double start, double sweep)
        {
            double[] ABC = pt.GetABC(Math.Tan(angle));
            PointD[] tmp = StraightLineArcIntersection(ABC[0], ABC[1], ABC[2], ct, r, start, sweep);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(Utility.GetUnitVector(angle), item - pt) >= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] StraightLineCircleIntersection(double A, double B, double C, PointD ct, double r)
        {
            return StraightLineArcIntersection(A, B, C, ct, r, 0, Angle.RadRound);
        }
        //public static PointD[] StraightLineObjectIntersection(SketchPad pad, double[] lineParams, ShapeBase obj, bool getNew = true)
        //{
        //    if (lineParams == null || lineParams.Length < 3) return null;
        //    List<PointD> res = new List<PointD>();
        //    PointD[] pts = null;
        //    LineSegmentBase lsb = obj as LineSegmentBase;
        //    bool convert = false;
        //    if (lsb != null)
        //    {
        //        if (lineParams.Length < 6)
        //        {
        //            pts = getNew ? LineSegmentStraightLineIntersection(lsb.Point1.NewXY, lsb.Point2.NewXY, lineParams[0], lineParams[1], lineParams[2]) :
        //                LineSegmentStraightLineIntersection(lsb.Point1.ToPointD(), lsb.Point2.ToPointD(), lineParams[0], lineParams[1], lineParams[2]);
        //            convert = true;
        //        }
        //        else
        //        {
        //            pts = getNew ? LineSegmentStraightLineIntersection(lsb.Point1.NewPxy, lsb.Point2.NewPxy, lineParams[3], lineParams[4], lineParams[5]) :
        //                LineSegmentStraightLineIntersection(lsb.Point1.Pxy, lsb.Point2.Pxy, lineParams[3], lineParams[4], lineParams[5]);
        //        }
        //    }
        //    else
        //    {
        //        RayBase ray = obj as RayBase;
        //        if (ray != null)
        //        {
        //            if (lineParams.Length < 6)
        //            {
        //                pts = getNew ? RayStraightLineIntersection(ray.SourcePoint.NewXY, ray.NewDirectedAngle, lineParams[0], lineParams[1], lineParams[2]) :
        //                    RayStraightLineIntersection(ray.SourcePoint.ToPointD(), ray.DirectedAngle.RadValue, lineParams[0], lineParams[1], lineParams[2]);
        //                convert = true;
        //            }
        //            else
        //            {
        //                pts = getNew ? RayStraightLineIntersection(ray.SourcePoint.NewPxy, ray.NewPDirectedAngle, lineParams[3], lineParams[4], lineParams[5]) :
        //                    RayStraightLineIntersection(ray.SourcePoint.Pxy, ray.DirectedAngle.PRadValue, lineParams[3], lineParams[4], lineParams[5]);
        //            }
        //        }
        //        else
        //        {
        //            PointSlopeLineBase slb = obj as PointSlopeLineBase;
        //            if (slb != null)//直线+直线
        //            {
        //                if (lineParams.Length < 6)
        //                {
        //                    pts = new PointD[] { getNew ? Utility.GetCrossPoint(lineParams[0], lineParams[1], lineParams[2], slb.NewA, slb.NewB, slb.NewC) :
        //                        Utility.GetCrossPoint(lineParams[0], lineParams[1], lineParams[2], slb.A, slb.B, slb.C) };
        //                    convert = true;
        //                }
        //                else
        //                {
        //                    res.Add(getNew ? Utility.GetCrossPoint(lineParams[3], lineParams[4], -lineParams[5], slb.NewPa, slb.NewPb, -slb.NewPc) :
        //                        Utility.GetCrossPoint(lineParams[3], lineParams[4], -lineParams[5], slb.Pa, slb.Pb, -slb.Pc));
        //                }
        //            }
        //            else
        //            {
        //                ThreePointsPartialCircleBase tppcb = obj as ThreePointsPartialCircleBase;
        //                if (tppcb != null)
        //                {
        //                    pts = getNew ? StraightLineArcIntersection(lineParams[0], lineParams[1], lineParams[2], tppcb.NewCenter, tppcb.NewRadius, tppcb.NewStart, tppcb.NewSweep) :
        //                        StraightLineArcIntersection(lineParams[0], lineParams[1], lineParams[2], tppcb.Center, tppcb.Radius, tppcb.Start.RadValue, tppcb.Sweep.RadValue);
        //                    convert = true;
        //                }
        //                else
        //                {
        //                    CircleLikeBase clb = obj as CircleLikeBase;
        //                    if (clb != null)//直线+圆
        //                    {
        //                        pts = getNew ? StraightLineCircleIntersection(lineParams[0], lineParams[1], lineParams[2], clb.NewCenter, clb.NewRadius) :
        //                             StraightLineCircleIntersection(lineParams[0], lineParams[1], lineParams[2], clb.Center, clb.Radius);
        //                        convert = true;
        //                    }
        //                    else
        //                    {
        //                        EllipseBase eb = obj as EllipseBase;
        //                        if (eb != null)//直线+椭圆
        //                        {
        //                            pts = getNew ? StraightLineEllipseIntersection(lineParams[0], lineParams[1], lineParams[2], eb.NewCenter, eb.NewLongAxisHalfLength, eb.NewShortAxisHalfLength, eb.NewFocusAngle) :
        //                                 StraightLineEllipseIntersection(lineParams[0], lineParams[1], lineParams[2], eb.Center, eb.LongAxisHalfLength, eb.ShortAxisHalfLength, eb.FocusAngle);
        //                            convert = true;
        //                        }
        //                        else
        //                        {
        //                            HyperbolaBase hb = obj as HyperbolaBase;
        //                            if (hb != null)//直线+双曲线
        //                            {
        //                                pts = getNew ? StraightLineHyperbolaIntersection(lineParams[0], lineParams[1], lineParams[2], hb.NewCenter, hb.NewRealAxisHalfLength, hb.NewImaginaryAxisHalfLength, hb.NewFocusAngle) :
        //                                     StraightLineHyperbolaIntersection(lineParams[0], lineParams[1], lineParams[2], hb.Center, hb.RealAxisHalfLength, hb.ImaginaryAxisHalfLength, hb.FocusAngle);
        //                                convert = true;
        //                            }
        //                            else
        //                            {
        //                                ParabolaBase pb = obj as ParabolaBase;
        //                                if (pb != null)//直线+抛物线
        //                                {
        //                                    pts = getNew ? StraightLineParabolaIntersection(lineParams[0], lineParams[1], lineParams[2], pb.NewCenter, pb.NewFocusDirectrixDistance, pb.NewFocusAngle) :
        //                                         StraightLineParabolaIntersection(lineParams[0], lineParams[1], lineParams[2], pb.Center, pb.FocusDirectrixDistance, pb.FocusAngle);
        //                                    convert = true;
        //                                }
        //                                else
        //                                {
        //                                    ICurveLike curs = obj as ICurveLike;
        //                                    if (curs != null)//直线+曲线
        //                                    {
        //                                        double[] tmp = null;
        //                                        if (lineParams.Length < 6)
        //                                        {
        //                                            tmp = pad.ABCtoPaPbPc(lineParams[0], lineParams[1], lineParams[2]);
        //                                        }
        //                                        foreach (PaintableCurve item in getNew ? curs.NewCurves : curs.Curves)
        //                                        {
        //                                            pts = item.StraightLineCurveIntersection(tmp == null ? lineParams[3] : tmp[0], tmp == null ? lineParams[4] : tmp[1], tmp == null ? lineParams[5] : tmp[2], (List<PointD> set) =>
        //                                            {
        //                                                if (obj is ICircle)
        //                                                {
        //                                                    if (set.Count >= 2) return true;
        //                                                }
        //                                                return false;
        //                                            });
        //                                            if (pts != null) res.AddRange(pts);
        //                                        }
        //                                        pts = null;
        //                                    }
        //                                    else
        //                                    {
        //                                        if (obj is PolygonBase || obj is AngleNDivider || obj is CoordinateBase)//直线+直线组
        //                                        {
        //                                            foreach (StraightLineBase item in obj.GetStraightLines())
        //                                            {
        //                                                pts = StraightLineObjectIntersection(pad, lineParams, item, getNew);
        //                                                if (pts != null) res.AddRange(pts);
        //                                            }
        //                                            pts = null;
        //                                        }
        //                                    }
        //                                }
        //                            }
        //                        }
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    if (pts != null)
        //    {
        //        if (convert && pad.Coordinate != null)
        //        {
        //            for (int i = 0; i < pts.Length; i++)
        //            {
        //                pts[i] = pad.Coordinate.XYToPxy(pts[i]);
        //            }
        //        }
        //        res.AddRange(pts);
        //    }
        //    if (res.Count == 0) return null;
        //    return res.ToArray();
        //}
        public static PointD[] StraightLineArcIntersection(double A, double B, double C, PointD ct, double r, double start, double sweep)
        {
            double dist = ct.DistanceTo(A, B, C);
            if (dist > r) return null;
            List<PointD> pts = new List<PointD>();
            if (dist == r)
            {
                pts.Add(ct.GetProjectivePoint(A, B, C));
            }
            else
            {
                if (A == 0)
                {
                    double tmp = Math.Sqrt(r * r - dist * dist);
                    pts.Add(new PointD(ct.X + tmp, -C / B));
                    pts.Add(new PointD(ct.X - tmp, -C / B));
                }
                else
                {
                    double yp1 = 0.5 / (B * B + A * A),
                        yp2 = -2 * ct.X * A * B + 2 * ct.Y * A * A - 2 * C * B,
                        yp3 = 2 * Math.Sqrt(-2 * ct.X * A * A * A * B * ct.Y - 2 * ct.Y * A * A * C * B - B * B * ct.Y * ct.Y * A * A + B * B * r * r * A * A - 2 * A * A * A * ct.X * C - A * A * A * A * ct.X * ct.X - A * A * C * C + A * A * A * A * r * r);
                    pts.Add(new PointD(-(yp1 * B * (yp2 + yp3) + C) / A, yp1 * (yp2 + yp3)));
                    pts.Add(new PointD(-(yp1 * B * (yp2 - yp3) + C) / A, yp1 * (yp2 - yp3)));
                }
            }
            for (int i = pts.Count - 1; i >= 0; i--)
            {
                if (!pts[i].IsNumberPoint || !Utility.InSweepRange(start, sweep, ct.GetAngle(pts[i])))
                {
                    pts.RemoveAt(i);
                }
            }
            if (pts.Count == 0) return null;
            return pts.ToArray();
        }
        public static PointD[] LineSegmentEllipseIntersection(PointD segpt1, PointD segpt2, PointD ct, double a, double b, double theta)
        {
            double[] ABC = segpt1.GetABC(segpt2);
            PointD[] tmp = StraightLineEllipseIntersection(ABC[0], ABC[1], ABC[2], ct, a, b, theta);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(item, segpt1, item, segpt2) <= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] RayEllipseIntersection(PointD pt, double angle, PointD ct, double a, double b, double theta)
        {
            double[] ABC = pt.GetABC(Math.Tan(angle));
            PointD[] tmp = StraightLineEllipseIntersection(ABC[0], ABC[1], ABC[2], ct, a, b, theta);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(Utility.GetUnitVector(angle), item - pt) >= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] StraightLineEllipseIntersection(double A, double B, double C, PointD ct, double a, double b, double theta)
        {
            List<PointD> pts = new List<PointD>();
            double sin = Math.Sin(theta), cos = Math.Cos(theta);
            if (A == 0)
            {
                double xp1 = 0.5 / (b * b + a * a * sin * sin - sin * sin * b * b),
                    xp2 = -2 * a * a * sin * ct.Y * cos * B + 2 * a * a * sin * sin * ct.X * B + 2 * b * b * ct.X * B + 2 * b * b * sin * ct.Y * cos * B - 2 * sin * sin * b * b * ct.X * B + 2 * b * b * sin * C * cos - 2 * a * a * sin * C * cos,
                    xp3 = 2 * Math.Sqrt(2 * b * b * sin * sin * a * a * ct.Y * ct.Y * B * B + 4 * b * b * sin * sin * a * a * C * ct.Y * B + b * b * b * b * a * a * B * B - a * a * a * a * sin * sin * C * C - 2 * b * b * a * a * C * ct.Y * B + sin * sin * sin * sin * b * b * b * b * ct.Y * ct.Y * B * B + b * b * b * b * sin * sin * C * C * cos * cos + a * a * a * a * sin * sin * C * C * cos * cos + 2 * b * b * sin * sin * a * a * C * C - b * b * b * b * sin * sin * ct.Y * ct.Y * B * B + a * a * a * a * sin * sin * b * b * B * B - 2 * a * a * sin * sin * sin * sin * b * b * C * C - a * a * a * a * sin * sin * ct.Y * ct.Y * B * B + a * a * a * a * sin * sin * sin * sin * ct.Y * ct.Y * B * B - sin * sin * b * b * b * b * a * a * B * B - b * b * a * a * ct.Y * ct.Y * B * B - 2 * b * b * sin * sin * C * C * cos * cos * a * a - 4 * a * a * sin * sin * sin * sin * b * b * C * ct.Y * B - 2 * a * a * a * a * sin * sin * C * ct.Y * B - b * b * b * b * sin * sin * C * C - 2 * a * a * sin * sin * sin * sin * b * b * ct.Y * ct.Y * B * B + 2 * a * a * a * a * sin * sin * sin * sin * C * ct.Y * B + 2 * sin * sin * sin * sin * b * b * b * b * C * ct.Y * B - 2 * b * b * b * b * sin * sin * C * ct.Y * B + a * a * a * a * sin * sin * ct.Y * ct.Y * cos * cos * B * B - 2 * a * a * sin * sin * ct.Y * ct.Y * cos * cos * B * B * b * b - 4 * a * a * sin * sin * ct.Y * cos * cos * B * b * b * C + 2 * a * a * a * a * sin * sin * ct.Y * cos * cos * B * C + b * b * b * b * sin * sin * ct.Y * ct.Y * cos * cos * B * B + 2 * b * b * b * b * sin * sin * ct.Y * cos * cos * B * C - b * b * a * a * C * C + a * a * a * a * sin * sin * sin * sin * C * C + sin * sin * sin * sin * b * b * b * b * C * C);
                pts.Add(new PointD(xp1 * (xp2 + xp3) / B, -C / B));
                pts.Add(new PointD(xp1 * (xp2 - xp3) / B, -C / B));
            }
            else
            {
                double yp1 = 0.5 / (sin * sin * a * a * A * A - b * b * sin * sin * A * A + sin * sin * b * b * B * B - sin * sin * a * a * B * B - a * a * A * A - b * b * B * B + 2 * b * b * sin * cos * A * B - 2 * a * a * sin * cos * A * B),
                    yp2 = -2 * sin * sin * b * b * B * C - 2 * b * b * sin * sin * ct.Y * A * A - 2 * a * a * ct.Y * A * A + 2 * b * b * sin * ct.Y * cos * A * B - 2 * a * a * sin * ct.Y * cos * A * B + 2 * sin * sin * a * a * B * C + 2 * b * b * B * C - 2 * b * b * sin * cos * A * C + 2 * a * a * sin * cos * ct.X * A * A + 2 * a * a * sin * cos * A * C + 2 * a * a * sin * sin * ct.X * A * B - 2 * sin * sin * b * b * ct.X * A * B + 2 * b * b * ct.X * A * B + 2 * sin * sin * a * a * ct.Y * A * A - 2 * b * b * sin * cos * ct.X * A * A,
                    yp3 = 2 * Math.Sqrt(a * a * a * a * A * A * A * A * b * b - a * a * A * A * A * A * b * b * ct.X * ct.X - a * a * A * A * b * b * C * C + 2 * sin * sin * sin * sin * b * b * b * b * B * C * ct.Y * A * A - 2 * b * b * b * b * sin * sin * ct.Y * A * A * A * ct.X * B - sin * sin * a * a * a * a * B * B * ct.Y * ct.Y * A * A + 2 * a * a * a * a * sin * sin * cos * cos * ct.X * A * A * A * C - 2 * a * a * ct.Y * A * A * b * b * B * C - 2 * a * a * ct.Y * A * A * A * b * b * ct.X * B + 2 * sin * sin * sin * sin * a * a * a * a * A * A * A * ct.X * C - 2 * a * a * A * A * A * b * b * ct.X * C + b * b * b * b * B * B * a * a * A * A + sin * sin * sin * sin * a * a * a * a * A * A * C * C - sin * sin * a * a * a * a * A * A * A * A * b * b + sin * sin * sin * sin * a * a * a * a * A * A * A * A * ct.X * ct.X + b * b * b * b * sin * sin * sin * sin * A * A * C * C - b * b * b * b * sin * sin * A * A * A * A * ct.X * ct.X + b * b * b * b * sin * sin * A * A * A * A * a * a - b * b * b * b * sin * sin * A * A * C * C + b * b * b * b * sin * sin * sin * sin * A * A * A * A * ct.X * ct.X - a * a * a * a * A * A * sin * sin * C * C - b * b * B * B * a * a * ct.Y * ct.Y * A * A - 4 * sin * sin * sin * sin * a * a * A * A * A * b * b * ct.X * C + 4 * sin * sin * a * a * A * A * A * b * b * ct.X * C + 2 * sin * sin * a * a * A * A * A * A * b * b * ct.X * ct.X + 2 * sin * sin * a * a * A * A * b * b * C * C - 2 * sin * sin * sin * sin * a * a * A * A * A * A * b * b * ct.X * ct.X + 2 * b * b * b * b * sin * sin * sin * sin * A * A * A * ct.X * C - 2 * b * b * b * b * sin * sin * A * A * A * ct.X * C + 4 * sin * sin * b * b * B * C * a * a * ct.Y * A * A - 4 * sin * sin * sin * sin * b * b * B * C * a * a * ct.Y * A * A - a * a * a * a * A * A * A * A * sin * sin * ct.X * ct.X - 2 * b * b * b * b * sin * sin * ct.Y * A * A * B * C - 4 * b * b * sin * sin * sin * sin * ct.Y * A * A * A * a * a * ct.X * B + 2 * b * b * b * b * sin * sin * sin * sin * ct.Y * A * A * A * ct.X * B - 2 * a * a * a * a * ct.Y * A * A * sin * sin * B * C - 2 * a * a * a * a * ct.Y * A * A * A * sin * sin * ct.X * B + 4 * a * a * ct.Y * A * A * A * sin * sin * b * b * ct.X * B + b * b * b * b * sin * sin * ct.Y * ct.Y * cos * cos * A * A * B * B - 2 * b * b * sin * sin * ct.Y * ct.Y * cos * cos * A * A * B * B * a * a + 2 * b * b * b * b * sin * sin * ct.Y * cos * cos * A * A * B * C - 4 * b * b * sin * sin * ct.Y * cos * cos * A * A * A * B * a * a * ct.X - 4 * b * b * sin * sin * ct.Y * cos * cos * A * A * B * a * a * C + 2 * b * b * b * b * sin * sin * ct.Y * cos * cos * A * A * A * B * ct.X + a * a * a * a * sin * sin * ct.Y * ct.Y * cos * cos * A * A * B * B + 2 * a * a * a * a * sin * sin * ct.Y * cos * cos * A * A * A * B * ct.X + 2 * a * a * a * a * sin * sin * ct.Y * cos * cos * A * A * B * C + b * b * b * b * sin * sin * cos * cos * A * A * C * C - 4 * b * b * sin * sin * cos * cos * A * A * A * C * a * a * ct.X - 2 * b * b * sin * sin * cos * cos * A * A * C * C * a * a + 2 * b * b * b * b * sin * sin * cos * cos * A * A * A * C * ct.X + a * a * a * a * sin * sin * cos * cos * ct.X * ct.X * A * A * A * A - 2 * a * a * sin * sin * cos * cos * ct.X * ct.X * A * A * A * A * b * b + a * a * a * a * sin * sin * cos * cos * A * A * C * C + 2 * a * a * a * a * sin * sin * sin * sin * ct.X * A * A * A * B * ct.Y + b * b * b * b * sin * sin * cos * cos * ct.X * ct.X * A * A * A * A + sin * sin * sin * sin * b * b * b * b * B * B * ct.Y * ct.Y * A * A + 2 * sin * sin * b * b * B * B * a * a * ct.Y * ct.Y * A * A - sin * sin * b * b * b * b * B * B * a * a * A * A - 2 * sin * sin * sin * sin * b * b * B * B * a * a * ct.Y * ct.Y * A * A + sin * sin * a * a * a * a * B * B * b * b * A * A + sin * sin * sin * sin * a * a * a * a * B * B * ct.Y * ct.Y * A * A - 2 * a * a * a * a * A * A * A * sin * sin * ct.X * C - b * b * b * b * B * B * sin * sin * ct.Y * ct.Y * A * A - 2 * b * b * b * b * sin * cos * A * A * A * B * a * a + 2 * a * a * a * a * sin * cos * A * A * A * B * b * b + 2 * sin * sin * sin * sin * a * a * a * a * B * C * ct.Y * A * A - 2 * sin * sin * sin * sin * a * a * A * A * b * b * C * C);
                pts.Add(new PointD(-(yp1 * B * (yp2 + yp3) + C) / A, yp1 * (yp2 + yp3)));
                pts.Add(new PointD(-(yp1 * B * (yp2 - yp3) + C) / A, yp1 * (yp2 - yp3)));
            }
            removeInvalidPoints(pts);
            if (pts.Count == 0) return null;
            return pts.ToArray();
        }
        public static PointD[] LineSegmentHyperbolaIntersection(PointD segpt1, PointD segpt2, PointD ct, double a, double b, double theta)
        {
            double[] ABC = segpt1.GetABC(segpt2);
            PointD[] tmp = StraightLineHyperbolaIntersection(ABC[0], ABC[1], ABC[2], ct, a, b, theta);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(item, segpt1, item, segpt2) <= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] RayHyperbolaIntersection(PointD pt, double angle, PointD ct, double a, double b, double theta)
        {
            double[] ABC = pt.GetABC(Math.Tan(angle));
            PointD[] tmp = StraightLineHyperbolaIntersection(ABC[0], ABC[1], ABC[2], ct, a, b, theta);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(new PointD(Math.Cos(angle), Math.Sin(angle)), item - pt) >= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] StraightLineHyperbolaIntersection(double A, double B, double C, PointD ct, double a, double b, double theta)
        {
            List<PointD> pts = new List<PointD>();
            double sin = Math.Sin(theta), cos = Math.Cos(theta);
            if (A == 0)
            {
                double xp1 = 0.5 / (-b * b + sin * sin * b * b + a * a * sin * sin),
                    xp2 = -2 * b * b * sin * ct.Y * cos * B + 2 * sin * sin * b * b * ct.X * B - 2 * a * a * sin * C * cos - 2 * b * b * ct.X * B - 2 * a * a * sin * ct.Y * cos * B + 2 * a * a * sin * sin * ct.X * B - 2 * b * b * sin * C * cos,
                    xp3 = 2 * Math.Sqrt(-2 * b * b * sin * sin * a * a * ct.Y * ct.Y * B * B - 4 * b * b * sin * sin * a * a * C * ct.Y * B + b * b * b * b * a * a * B * B - a * a * a * a * sin * sin * C * C + 2 * b * b * a * a * C * ct.Y * B + sin * sin * sin * sin * b * b * b * b * ct.Y * ct.Y * B * B + b * b * b * b * sin * sin * C * C * cos * cos + a * a * a * a * sin * sin * C * C * cos * cos - 2 * b * b * sin * sin * a * a * C * C - b * b * b * b * sin * sin * ct.Y * ct.Y * B * B - a * a * a * a * sin * sin * b * b * B * B + 2 * a * a * sin * sin * sin * sin * b * b * C * C - a * a * a * a * sin * sin * ct.Y * ct.Y * B * B + a * a * a * a * sin * sin * sin * sin * ct.Y * ct.Y * B * B - sin * sin * b * b * b * b * a * a * B * B + b * b * a * a * ct.Y * ct.Y * B * B + 2 * b * b * sin * sin * C * C * cos * cos * a * a + 4 * a * a * sin * sin * sin * sin * b * b * C * ct.Y * B - 2 * a * a * a * a * sin * sin * C * ct.Y * B - b * b * b * b * sin * sin * C * C + 2 * a * a * sin * sin * sin * sin * b * b * ct.Y * ct.Y * B * B + 2 * a * a * a * a * sin * sin * sin * sin * C * ct.Y * B + 2 * sin * sin * sin * sin * b * b * b * b * C * ct.Y * B - 2 * b * b * b * b * sin * sin * C * ct.Y * B + a * a * a * a * sin * sin * ct.Y * ct.Y * cos * cos * B * B + 2 * a * a * sin * sin * ct.Y * ct.Y * cos * cos * B * B * b * b + 4 * a * a * sin * sin * ct.Y * cos * cos * B * b * b * C + 2 * a * a * a * a * sin * sin * ct.Y * cos * cos * B * C + b * b * b * b * sin * sin * ct.Y * ct.Y * cos * cos * B * B + 2 * b * b * b * b * sin * sin * ct.Y * cos * cos * B * C + b * b * a * a * C * C + a * a * a * a * sin * sin * sin * sin * C * C + sin * sin * sin * sin * b * b * b * b * C * C);
                pts.Add(new PointD(xp1 * (xp2 + xp3) / B, -C / B));
                pts.Add(new PointD(xp1 * (xp2 - xp3) / B, -C / B));
            }
            else
            {
                double yp1 = 0.5 / (-2 * a * a * sin * cos * A * B - a * a * A * A + b * b * B * B + b * b * sin * sin * A * A + sin * sin * a * a * A * A - a * a * sin * sin * B * B - sin * sin * b * b * B * B - 2 * b * b * sin * cos * A * B),
                 yp2 = 2 * sin * sin * a * a * ct.Y * A * A + 2 * a * a * sin * sin * ct.X * A * B + 2 * b * b * sin * cos * A * C - 2 * b * b * sin * ct.Y * cos * A * B + 2 * a * a * sin * cos * ct.X * A * A - 2 * a * a * ct.Y * A * A - 2 * b * b * ct.X * A * B + 2 * a * a * sin * sin * B * C - 2 * b * b * B * C + 2 * a * a * sin * cos * A * C + 2 * b * b * sin * cos * ct.X * A * A + 2 * sin * sin * b * b * B * C + 2 * sin * sin * b * b * ct.X * A * B + 2 * b * b * sin * sin * ct.Y * A * A - 2 * a * a * sin * ct.Y * cos * A * B,
                 yp3 = 2 * Math.Sqrt(-2 * a * a * a * a * sin * sin * ct.X * A * A * A * B * ct.Y - 2 * a * a * A * A * A * A * sin * sin * b * b * ct.X * ct.X + 2 * sin * sin * sin * sin * b * b * b * b * B * C * ct.Y * A * A + 2 * b * b * sin * sin * sin * sin * A * A * A * A * a * a * ct.X * ct.X - a * a * a * a * sin * sin * B * B * ct.Y * ct.Y * A * A - 2 * b * b * b * b * B * C * sin * sin * ct.Y * A * A + b * b * b * b * sin * sin * cos * cos * A * A * C * C - 2 * a * a * a * a * sin * cos * A * A * A * B * b * b + 2 * a * a * ct.Y * A * A * A * b * b * ct.X * B + 2 * a * a * ct.Y * A * A * b * b * B * C + 2 * b * b * b * b * sin * sin * cos * cos * A * A * C * ct.Y * B + 2 * a * a * A * A * A * b * b * ct.X * C + b * b * B * B * a * a * ct.Y * ct.Y * A * A + b * b * b * b * sin * sin * sin * sin * A * A * A * A * ct.X * ct.X + b * b * b * b * sin * sin * A * A * A * A * a * a + b * b * b * b * sin * sin * sin * sin * A * A * C * C - b * b * b * b * sin * sin * A * A * C * C - b * b * b * b * sin * sin * A * A * A * A * ct.X * ct.X + sin * sin * sin * sin * a * a * a * a * A * A * A * A * ct.X * ct.X + sin * sin * a * a * a * a * A * A * A * A * b * b + sin * sin * sin * sin * a * a * a * a * A * A * C * C - a * a * a * a * A * A * A * A * sin * sin * ct.X * ct.X - a * a * a * a * A * A * sin * sin * C * C + 4 * sin * sin * sin * sin * a * a * ct.Y * A * A * A * b * b * ct.X * B - a * a * a * a * A * A * A * A * b * b + b * b * b * b * B * B * a * a * A * A + a * a * A * A * b * b * C * C + a * a * A * A * A * A * b * b * ct.X * ct.X + 4 * b * b * sin * sin * cos * cos * A * A * A * C * a * a * ct.X + 2 * b * b * sin * sin * cos * cos * A * A * C * C * a * a + 2 * b * b * b * b * sin * sin * cos * cos * A * A * A * C * ct.X + 4 * b * b * sin * sin * cos * cos * A * A * C * a * a * ct.Y * B + b * b * b * b * sin * sin * ct.Y * ct.Y * cos * cos * A * A * B * B + 4 * b * b * sin * sin * ct.Y * cos * cos * A * A * A * B * a * a * ct.X + a * a * a * a * sin * sin * cos * cos * ct.X * ct.X * A * A * A * A + 2 * b * b * b * b * sin * sin * ct.Y * cos * cos * A * A * A * B * ct.X + 2 * b * b * sin * sin * ct.Y * ct.Y * cos * cos * A * A * B * B * a * a + 2 * a * a * a * a * sin * sin * cos * cos * ct.X * A * A * A * C + 2 * a * a * sin * sin * cos * cos * ct.X * ct.X * A * A * A * A * b * b + 2 * a * a * a * a * sin * sin * cos * cos * ct.X * A * A * A * ct.Y * B - 2 * a * a * a * a * ct.Y * A * A * sin * sin * B * C - 2 * b * b * b * b * ct.X * A * A * A * B * sin * sin * ct.Y + a * a * a * a * sin * sin * cos * cos * A * A * C * C + 2 * a * a * a * a * sin * sin * cos * cos * A * A * C * ct.Y * B + b * b * b * b * sin * sin * cos * cos * ct.X * ct.X * A * A * A * A + 2 * sin * sin * sin * sin * b * b * b * b * ct.X * A * A * A * B * ct.Y + a * a * a * a * sin * sin * ct.Y * ct.Y * cos * cos * A * A * B * B - b * b * b * b * B * B * sin * sin * ct.Y * ct.Y * A * A - 2 * b * b * B * B * sin * sin * a * a * ct.Y * ct.Y * A * A + 2 * b * b * sin * sin * sin * sin * A * A * a * a * C * C + 4 * b * b * sin * sin * sin * sin * A * A * A * a * a * ct.X * C + 2 * b * b * b * b * sin * sin * sin * sin * A * A * A * ct.X * C - 2 * b * b * b * b * sin * sin * A * A * A * ct.X * C + 2 * sin * sin * sin * sin * a * a * a * a * A * A * A * ct.X * C + 2 * a * a * sin * sin * sin * sin * B * B * b * b * ct.Y * ct.Y * A * A - a * a * a * a * sin * sin * B * B * b * b * A * A + a * a * a * a * sin * sin * sin * sin * B * B * ct.Y * ct.Y * A * A + sin * sin * sin * sin * b * b * b * b * B * B * ct.Y * ct.Y * A * A - sin * sin * b * b * b * b * B * B * a * a * A * A - 2 * b * b * b * b * sin * cos * A * A * A * B * a * a - 2 * a * a * A * A * sin * sin * b * b * C * C - 2 * a * a * a * a * A * A * A * sin * sin * ct.X * C - 4 * a * a * A * A * A * sin * sin * b * b * ct.X * C + 2 * sin * sin * sin * sin * a * a * a * a * ct.Y * A * A * A * ct.X * B - 4 * sin * sin * a * a * ct.Y * A * A * A * b * b * ct.X * B + 2 * sin * sin * sin * sin * a * a * a * a * ct.Y * A * A * B * C - 4 * sin * sin * a * a * ct.Y * A * A * b * b * B * C + 4 * sin * sin * sin * sin * a * a * ct.Y * A * A * b * b * B * C);
                pts.Add(new PointD(-(yp1 * B * (yp2 + yp3) + C) / A, yp1 * (yp2 + yp3)));
                pts.Add(new PointD(-(yp1 * B * (yp2 - yp3) + C) / A, yp1 * (yp2 - yp3)));
            }
            removeInvalidPoints(pts);
            if (pts.Count == 0) return null;
            return pts.ToArray();
        }
        public static PointD[] LineSegmentParabolaIntersection(PointD segpt1, PointD segpt2, PointD ct, double p, double theta)
        {
            double[] ABC = segpt1.GetABC(segpt2);
            PointD[] tmp = StraightLineParabolaIntersection(ABC[0], ABC[1], ABC[2], ct, p, theta);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(item, segpt1, item, segpt2) <= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] RayParabolaIntersection(PointD pt, double angle, PointD ct, double p, double theta)
        {
            double[] ABC = pt.GetABC(Math.Tan(angle));
            PointD[] tmp = StraightLineParabolaIntersection(ABC[0], ABC[1], ABC[2], ct, p, theta);//无效点在这里排除
            if (tmp == null) return null;
            List<PointD> res = new List<PointD>();
            foreach (PointD item in tmp)
            {
                if (Utility.ScalarProduct(new PointD(Math.Cos(angle), Math.Sin(angle)), item - pt) >= 0)
                {
                    res.Add(item);
                }
            }
            if (res.Count == 0) return null;
            return res.ToArray();
        }
        public static PointD[] StraightLineParabolaIntersection(double A, double B, double C, PointD ct, double p, double theta)
        {
            List<PointD> pts = new List<PointD>();
            double sin = Math.Sin(theta), cos = Math.Cos(theta);
            if (A == 0)
            {
                double xp1 = 0.5 / (sin * sin),
                    xp2 = 2 * sin * sin * ct.X * B + 2 * p * cos * B - 2 * sin * C * cos - 2 * sin * ct.Y * cos * B,
                    xp3 = 2 * Math.Sqrt(p * p * cos * cos * B * B - 2 * p * cos * cos * B * sin * C - 2 * p * cos * cos * B * B * sin * ct.Y + sin * sin * C * C * cos * cos + 2 * sin * sin * C * cos * cos * ct.Y * B + sin * sin * ct.Y * ct.Y * cos * cos * B * B + sin * sin * sin * sin * C * C - 2 * sin * sin * C * ct.Y * B - 2 * sin * sin * sin * p * ct.Y * B * B - 2 * sin * sin * sin * p * C * B + 2 * sin * sin * sin * sin * C * ct.Y * B + sin * sin * sin * sin * ct.Y * ct.Y * B * B - sin * sin * C * C - sin * sin * ct.Y * ct.Y * B * B);
                pts.Add(new PointD(xp1 * (xp2 + xp3) / B, -C / B));
                pts.Add(new PointD(xp1 * (xp2 - xp3) / B, -C / B));
            }
            else
            {
                double yp1 = 0.5 / (-sin * sin * B * B - 2 * cos * sin * A * B + sin * sin * A * A - A * A),
                    yp2 = 2 * sin * sin * B * C - 2 * cos * ct.Y * sin * A * B + 2 * cos * sin * A * C - 2 * ct.Y * A * A - 2 * p * sin * A * A + 2 * sin * sin * ct.X * A * B + 2 * ct.Y * sin * sin * A * A + 2 * cos * sin * ct.X * A * A + 2 * p * cos * A * B,
                    yp3 = 2 * Math.Sqrt(2 * sin * sin * sin * sin * B * C * ct.Y * A * A - 2 * ct.Y * A * A * A * p * cos * B - 2 * A * A * A * p * cos * C + cos * cos * sin * sin * A * A * C * C + cos * cos * sin * sin * ct.X * ct.X * A * A * A * A + p * p * cos * cos * A * A * B * B - sin * sin * B * B * ct.Y * ct.Y * A * A + sin * sin * sin * sin * B * B * ct.Y * ct.Y * A * A + 2 * sin * sin * sin * sin * A * A * A * ct.X * C - 2 * A * A * A * A * p * cos * ct.X - 2 * A * A * A * sin * sin * ct.X * C + p * p * sin * sin * A * A * A * A + sin * sin * sin * sin * A * A * C * C - A * A * A * A * sin * sin * ct.X * ct.X - A * A * sin * sin * C * C + sin * sin * sin * sin * A * A * A * A * ct.X * ct.X - 2 * sin * sin * sin * B * B * p * ct.Y * A * A - 2 * sin * sin * B * C * ct.Y * A * A - 2 * sin * sin * sin * B * C * p * A * A + cos * cos * ct.Y * ct.Y * sin * sin * A * A * B * B + 2 * cos * cos * ct.Y * sin * sin * A * A * B * C + 2 * sin * sin * sin * sin * ct.X * A * A * A * B * ct.Y - 2 * cos * cos * sin * ct.X * A * A * A * p * B + 2 * cos * cos * ct.Y * sin * sin * A * A * A * B * ct.X - 2 * cos * cos * ct.Y * sin * A * A * B * B * p + 2 * cos * cos * sin * sin * A * A * A * C * ct.X - 2 * cos * cos * sin * A * A * C * p * B - 2 * ct.Y * A * A * A * sin * sin * ct.X * B - 2 * p * sin * sin * sin * A * A * A * ct.X * B - 2 * p * p * sin * A * A * A * cos * B);
                pts.Add(new PointD(-(yp1 * B * (yp2 + yp3) + C) / A, yp1 * (yp2 + yp3)));
                pts.Add(new PointD(-(yp1 * B * (yp2 - yp3) + C) / A, yp1 * (yp2 - yp3)));
            }
            removeInvalidPoints(pts);
            if (pts.Count == 0) return null;
            return pts.ToArray();
        }
        public static PointD[] LineSegmentsIntersection(PointD seg1pt1, PointD seg1pt2, PointD seg2pt1, PointD seg2pt2)
        {
            if (CountLineSegmentsIntersections(seg1pt1, seg1pt2, seg2pt1, seg2pt2) == 0) return null;
            return new PointD[] { Utility.GetCrossPoint(seg1pt1, seg1pt2.GetSlope(seg1pt1), seg2pt1, seg2pt2.GetSlope(seg2pt1)) };
        }
        public static PointD[] LineSegmentRayIntersection(PointD segpt1, PointD segpt2, PointD raypt, double rayAngle)
        {
            PointD pt = Utility.GetCrossPoint(segpt1, segpt1.GetSlope(segpt2), raypt, Math.Tan(rayAngle));
            if (rayAngle < 0.5 * Math.PI)
            {
                if (raypt.X > Math.Max(segpt1.X, segpt2.X) || raypt.Y > Math.Max(segpt1.Y, segpt2.Y) || pt.X < raypt.X && pt.Y < raypt.Y)
                {
                    return null;
                }
            }
            else if (rayAngle < Math.PI)
            {
                if (raypt.X < Math.Min(segpt1.X, segpt2.X) || raypt.Y > Math.Max(segpt1.Y, segpt2.Y) || pt.X > raypt.X && pt.Y < raypt.Y)
                {
                    return null;
                }
            }
            else if (rayAngle < 1.5 * Math.PI)
            {
                if (raypt.X < Math.Min(segpt1.X, segpt2.X) || raypt.Y < Math.Min(segpt1.Y, segpt2.Y) || pt.X > raypt.X && pt.Y > raypt.Y)
                {
                    return null;
                }
            }
            else
            {
                if (raypt.X > Math.Max(segpt1.X, segpt2.X) || raypt.Y < Math.Min(segpt1.Y, segpt2.Y) || pt.X < raypt.X && pt.Y > raypt.Y)
                {
                    return null;
                }
            }
            if (Utility.IsClockwise(raypt, pt, segpt1) == Utility.IsClockwise(raypt, pt, segpt2))
            {
                return null;
            }
            return new PointD[] { pt };
        }
        public static PointD[] RaysIntersection(PointD ray1pt, double ray1Angle, PointD ray2pt, double ray2Angle)
        {
            PointD pt = Utility.GetCrossPoint(ray1pt, Math.Tan(ray1Angle), ray2pt, Math.Tan(ray2Angle));
            bool has = false;
            if (ray1Angle < 0.5 * Math.PI)
            {
                if (ray2Angle < 0.5 * Math.PI)
                {
                    if (pt.X >= ray1pt.X && pt.X >= ray2pt.X && pt.Y >= ray1pt.Y && pt.Y >= ray2pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < Math.PI)
                {
                    if (pt.X >= ray1pt.X && pt.X <= ray2pt.X && pt.Y >= ray1pt.Y && pt.Y >= ray2pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < 1.5 * Math.PI)
                {
                    if (pt.X >= ray1pt.X && pt.X <= ray2pt.X && pt.Y >= ray1pt.Y && pt.Y <= ray2pt.Y)
                    {
                        has = true;
                    }
                }
                else
                {
                    if (pt.X >= ray1pt.X && pt.X >= ray2pt.X && pt.Y >= ray1pt.Y && pt.Y <= ray2pt.Y)
                    {
                        has = true;
                    }
                }
            }
            else if (ray1Angle < Math.PI)
            {
                if (ray2Angle < 0.5 * Math.PI)
                {
                    if (pt.X >= ray2pt.X && pt.X <= ray1pt.X && pt.Y >= ray2pt.Y && pt.Y >= ray1pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < Math.PI)
                {
                    if (pt.X <= ray1pt.X && pt.X <= ray2pt.X && pt.Y >= ray2pt.Y && pt.Y >= ray1pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < 1.5 * Math.PI)
                {
                    if (pt.X <= ray1pt.X && pt.X <= ray2pt.X && pt.Y >= ray1pt.Y && pt.Y <= ray2pt.Y)
                    {
                        has = true;
                    }
                }
                else
                {
                    if (pt.X >= ray2pt.X && pt.X <= ray1pt.X && pt.Y >= ray1pt.Y && pt.Y <= ray2pt.Y)
                    {
                        has = true;
                    }
                }
            }
            else if (ray1Angle < 1.5 * Math.PI)
            {
                if (ray2Angle < 0.5 * Math.PI)
                {
                    if (pt.X >= ray2pt.X && pt.X <= ray1pt.X && pt.Y >= ray2pt.Y && pt.Y <= ray1pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < Math.PI)
                {
                    if (pt.X <= ray1pt.X && pt.X <= ray2pt.X && pt.Y >= ray2pt.Y && pt.Y <= ray1pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < 1.5 * Math.PI)
                {
                    if (pt.X <= ray1pt.X && pt.X <= ray2pt.X && pt.Y <= ray1pt.Y && pt.Y <= ray2pt.Y)
                    {
                        has = true;
                    }
                }
                else
                {
                    if (pt.X >= ray2pt.X && pt.X <= ray1pt.X && pt.Y <= ray2pt.Y && pt.Y <= ray1pt.Y)
                    {
                        has = true;
                    }
                }
            }
            else
            {
                if (ray2Angle < 0.5 * Math.PI)
                {
                    if (pt.X >= ray1pt.X && pt.X >= ray2pt.X && pt.Y >= ray2pt.Y && pt.Y <= ray1pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < Math.PI)
                {
                    if (pt.X >= ray1pt.X && pt.X <= ray2pt.X && pt.Y >= ray2pt.Y && pt.Y <= ray1pt.Y)
                    {
                        has = true;
                    }
                }
                else if (ray2Angle < 1.5 * Math.PI)
                {
                    if (pt.X >= ray1pt.X && pt.X <= ray2pt.X && pt.Y <= ray1pt.Y && pt.Y <= ray2pt.Y)
                    {
                        has = true;
                    }
                }
                else
                {
                    if (pt.X >= ray1pt.X && pt.X >= ray2pt.X && pt.Y <= ray1pt.Y && pt.Y <= ray2pt.Y)
                    {
                        has = true;
                    }
                }
            }
            if (has) return new PointD[] { pt };
            return null;
        }
        public static PointD[] RayStraightLineIntersection(PointD raypt, double rayAngle, PointD linept, double lineSlope)
        {
            PointD pt = Utility.GetCrossPoint(raypt, Math.Tan(rayAngle), linept, lineSlope);
            if (inRayDirection(raypt, rayAngle, pt)) return new PointD[] { pt };
            return null;
        }
        static bool inRayDirection(PointD raypt, double rayAngle, PointD pt)
        {
            if (rayAngle < 0.5 * Math.PI)
            {
                if (pt.X >= raypt.X && pt.Y >= raypt.Y)
                {
                    return true;
                }
            }
            else if (rayAngle < Math.PI)
            {
                if (pt.X <= raypt.X && pt.Y >= raypt.Y)
                {
                    return true;
                }
            }
            else if (rayAngle < 1.5 * Math.PI)
            {
                if (pt.X <= raypt.X && pt.Y <= raypt.Y)
                {
                    return true;
                }
            }
            else
            {
                if (pt.X >= raypt.X && pt.Y <= raypt.Y)
                {
                    return true;
                }
            }
            return false;
        }
        public static PointD[] RayStraightLineIntersection(PointD raypt, double rayAngle, double A, double B, double C)
        {
            double[] abc = raypt.GetABC(Math.Tan(rayAngle));
            PointD pt = Utility.GetCrossPoint(abc[0], abc[1], abc[2], A, B, C);
            if (inRayDirection(raypt, rayAngle, pt)) return new PointD[] { pt };
            return null;
        }
        public static PointD[] LineSegmentStraightLineIntersection(PointD segpt1, PointD segpt2, PointD linept, double lineSlope)
        {
            if (CountLineSegmentStraightLineIntersections(segpt1, segpt2, linept, lineSlope) == 0) return null;
            return new PointD[] { Utility.GetCrossPoint(segpt1, segpt2.GetSlope(segpt1), linept, lineSlope) };
        }
        public static PointD[] LineSegmentStraightLineIntersection(PointD segpt1, PointD segpt2, double A, double B, double C)
        {
            if (CountLineSegmentStraightLineIntersections(segpt1, segpt2, A, B, C) == 0) return null;
            double[] abc = segpt1.GetABC(segpt2);
            return new PointD[] { Utility.GetCrossPoint(abc[0], abc[1], abc[2], A, B, C) };
        }
        static void removeInvalidPoints(IList<PointD> pts)
        {
            for (int i = pts.Count - 1; i >= 0; i--)
            {
                if (!pts[i].IsNumberPoint)
                {
                    pts.RemoveAt(i);
                }
            }
        }
        #region 判断交点个数
        public static int CountLineSegmentsIntersections(PointD seg1pt1, PointD seg1pt2, PointD seg2pt1, PointD seg2pt2)
        {
            if (Math.Min(seg1pt1.X, seg1pt2.X) > Math.Max(seg2pt1.X, seg2pt2.X) ||
                Math.Min(seg2pt1.Y, seg2pt2.Y) > Math.Max(seg1pt1.Y, seg1pt2.Y) ||
                Math.Min(seg2pt1.X, seg2pt2.X) > Math.Max(seg1pt1.X, seg1pt2.X) ||
                Math.Min(seg1pt1.Y, seg1pt2.Y) > Math.Max(seg2pt1.Y, seg2pt2.Y))
            {
                return 0;
            }
            else
            {
                return Utility.OnSameSide(seg1pt1, seg1pt2, seg2pt1, seg2pt2) || 
                    Utility.OnSameSide(seg2pt1, seg2pt2, seg1pt1, seg1pt2) ? 0 : 1;
            }
        }
        public static int CountLineSegmentStraightLineIntersections(PointD segpt1, PointD segpt2, PointD linept, double lineSlope)
        {
            int sgn1 = Utility.Sign(linept, lineSlope, segpt1), sgn2 = Utility.Sign(linept, lineSlope, segpt2);
            return sgn1 != sgn2 || sgn1 == 0 ? 1 : 0;
        }
        public static int CountLineSegmentStraightLineIntersections(PointD segpt1, PointD segpt2, double A, double B, double C)
        {
            int sgn1 = Utility.Sign(A, B, C, segpt1), sgn2 = Utility.Sign(A, B, C, segpt2);
            return sgn1 != sgn2 || sgn1 == 0 ? 1 : 0;
        }
        public static int CountLineSegmentRayIntersections(PointD segpt1, PointD segpt2, PointD raypt, double rayAngle)
        {
            //double ang1 = raypt.GetAngle(segpt1), ang2 = raypt.GetAngle(segpt2), 
            //    k = segpt1.GetSlope(segpt2), sign = Utility.Sign(segpt1, k, raypt),
            //    minY = Math.Min(segpt1.Y, segpt2.Y), maxY = Math.Max(segpt1.Y, segpt2.Y);
            //if (raypt.Y <= minY || raypt.Y >= maxY || k > 0 && sign == -1 || k < 0 && sign == 1)
            //{
            //    return rayAngle >= Math.Min(ang1, ang2) && rayAngle <= Math.Max(ang1, ang2) ? 1 : 0;
            //}
            //else
            //{
            //    return rayAngle >= Math.Max(ang1, ang2) || rayAngle <= Math.Min(ang1, ang2) ? 1 : 0;
            //}
            PointD[] pts = LineSegmentRayIntersection(segpt1, segpt2, raypt, rayAngle);
            return pts == null ? 0 : pts.Length;
        }
        //public static int CountRaysIntersections(PointD ray1pt, double ray1Angle, PointD ray2pt, double ray2Angle)
        //{
        //    double ang = ray2pt.GetAngle(ray1pt);
        //    return ray2Angle >= Math.Min(ray1Angle, ang) && ray2Angle <= Math.Max(ray1Angle, ang) ? 1 : 0;
        //}
        //public static int CountRayStraightLineIntersections(PointD raypt, double rayAngle, PointD linept, double lineSlope)
        //{
        //    double ang = Math.Atan(lineSlope);
        //    if (ang < 0) ang += Math.PI;
        //    return CountRaysIntersections(raypt, rayAngle, linept, ang) == 1 ||
        //        CountRaysIntersections(raypt, rayAngle, linept, ang + Math.PI) == 1 ? 1 : 0;
        //}
        public static int CountCirclesIntersections(PointD ct1, double r1, PointD ct2, double r2)
        {
            double delta = ct1.DistanceTo(ct2) - r1 - r2;
            if (delta > 0) return 0;
            if (delta == 0) return 1;
            delta = ct1.DistanceTo(ct2) - Math.Abs(r1 - r2);
            if (delta < 0) return 0;
            if (delta == 0) return 1;
            return 2;
        }
        #endregion
    }
}
